/* ============================================================ AI-X — site.js Header/footer giữ site hiện tại (§5.1), bộ chọn chẩn đoán 3 bước (§6.1), máy tính ROI (§9.2 — khớp checkpoint), accordion FAQ, thanh anchor hub, render nhóm/trang chủ. Thuần JS không phụ thuộc Odoo. ============================================================ */ (function () { "use strict"; var A = window.AIX || {}; var esc = function (s) { return String(s == null ? "" : s).replace(/[&<>"']/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]; }); }; var params = function () { return new URLSearchParams(location.search); }; /* ---------- Header placeholder (§5.1: giữ site hiện tại) ---------- */ function buildHeader() { var host = document.getElementById("aix-header"); if (!host) return; host.innerHTML = '
' + 'AIAI-X.vn' + '
"; } /* ---------- Footer (§5.6) ---------- */ function buildFooter() { var host = document.getElementById("aix-footer"); if (!host) return; host.innerHTML = '
' + '" + '
'; } /* ---------- Bộ chọn chẩn đoán (§6.1) ---------- */ window.AIX_selector = function (root) { if (!root) return; var groups = A.groups, activeGroup = groups[0], activeInd = groups[0].industries[2], activeProblem = groups[0].industries[2].probs[0]; var el = function (q) { return root.querySelector(q); }; function groupChips() { return groups.map(function (g) { return '"; }).join(""); } function indChips() { return activeGroup.industries.map(function (i) { return '"; }).join(""); } function problemChips() { return activeInd.probs.map(function (p) { return '"; }).join(""); } function render() { el(".js-step-group").innerHTML = groupChips(); el(".js-step-ind").innerHTML = indChips(); el(".js-step-prob").innerHTML = problemChips(); el(".js-confirm").innerHTML = '
Bạn sẽ chẩn đoán: ' + esc(activeInd.name) + " · " + esc(activeProblem) + '/chan-doan-nhanh?nganh=' + activeInd.slug + "&van-de=" + esc(activeProblem).toLowerCase().replace(/[^a-z0-9]+/g, "-") + "
"; } root.addEventListener("click", function (e) { var b = e.target.closest("button.chip"); if (!b) return; if (b.dataset.g) { activeGroup = groups.find(function (g) { return g.slug === b.dataset.g; }); activeInd = activeGroup.industries[0]; activeProblem = activeInd.probs[0]; } else if (b.dataset.i) { activeInd = activeGroup.industries.find(function (i) { return i.slug === b.dataset.i; }); activeProblem = activeInd.probs[0]; } else if (b.dataset.p) { activeProblem = b.dataset.p; } render(); }); render(); }; /* ---------- Máy tính ROI (§9.2) ---------- */ window.AIX_roi = function (root) { if (!root) return; /* Kịch bản động: trang ROI đặt window.AIX_ROI_SC trước khi gọi. Mặc định giữ hub.roi (thi-cong-noi-that) để không phá checkpoint §9.2. */ var sc = window.AIX_ROI_SC || { baseRevenue: 500, budget: 25.5, revenueOptions: [100, 300, 500, 1000], items: A.hub.roi.items }; var el = function (q) { return document.querySelector(q); }; var fmt = function (n) { return n.toLocaleString("vi-VN"); }; var rev = sc.baseRevenue, budget = sc.budget, mode = 1.0; /* nút doanh thu theo kịch bản (render bởi trang nếu có; fallback giữ HTML tĩnh) */ var revHost = root.querySelector(".js-rev-chips"); if (revHost && sc.revenueOptions) { revHost.innerHTML = sc.revenueOptions.map(function (r) { return '"; }).join(""); } function compute() { /* Khoản tỷ lệ theo biến quy mô (§9.2): revenue/purchase/material theo doanh thu; headcount theo nhân sự; fixed giữ nguyên. Giá trị mẫu = mức sc.baseRevenue của kịch bản. */ var rFactor = rev / sc.baseRevenue; var headFactor = rev / sc.baseRevenue; /* nhân sự tỷ lệ thuận doanh thu */ var items = sc.items.map(function (it) { var base = it.value; var mult = 1; if (it.scale === "revenue") mult = rFactor; else if (it.scale === "headcount") mult = headFactor; else if (it.scale === "fixed") mult = 1; else mult = rFactor; /* purchase/material/change_order: tỷ lệ doanh thu */ return { name: it.name, type: it.type, value: base * mult * mode }; }); var total = items.reduce(function (a, i) { return a + i.value; }, 0); var payback = budget / total * 12; var roi3 = (total * 3 - budget) / budget * 100; return { total: total, payback: payback, roi3: roi3, items: items }; } function renderTable() { var host = el(".js-roi-table"); if (!host) return; var r = compute(); host.innerHTML = r.items.map(function (it, idx) { var a = sc.items[idx]; var lab = a.type === "cash" ? "Tiền mặt" : a.type === "wc" ? "Vốn lưu động" : "Năng lực"; return "" + a.n + "" + esc(a.name) + "" + esc(lab) + "" + esc(a.before) + "" + esc(a.after) + "" + esc(a.improv) + "" + esc(a.formula) + "" + it.value.toLocaleString("vi-VN", { maximumFractionDigits: 2 }) + " tỷ"; }).join("") + 'Tổng (đã nhân mức hiện thực hóa ' + (mode === 1 ? "100" : mode === 0.75 ? "75" : "50") + '%)' + r.total.toLocaleString("vi-VN", { maximumFractionDigits: 1 }) + " tỷ"; } function render() { var r = compute(); el(".js-roi-big").textContent = r.total.toLocaleString("vi-VN", { maximumFractionDigits: 1 }) + " tỷ/năm"; el(".js-roi-payback").textContent = r.payback.toFixed(1).replace(".", ",") + " tháng"; el(".js-roi-roi3").textContent = "~" + Math.round(r.roi3).toLocaleString("vi-VN") + "%"; el(".js-roi-acc3").textContent = (r.total * 3).toLocaleString("vi-VN", { maximumFractionDigits: 1 }) + " tỷ"; el(".js-roi-scenario").textContent = "Theo kịch bản · " + (mode === 1 ? "100%" : mode === 0.75 ? "75%" : "50%") + " · Doanh thu " + fmt(rev) + " tỷ · Ngân sách " + fmt(budget) + " tỷ"; renderTable(); } root.addEventListener("click", function (e) { var b = e.target.closest("button.chip"); if (!b) return; if (b.dataset.rev) { rev = +b.dataset.rev; } else if (b.dataset.budget) { budget = +b.dataset.budget; } else if (b.dataset.mode) { mode = +b.dataset.mode; } var all = root.querySelectorAll(".roi-group .chips .chip"); all.forEach(function (c) { var group = c.closest(".roi-group"); if ((c.dataset.rev && c.dataset.rev === String(rev)) || (c.dataset.budget && c.dataset.budget === String(budget)) || (c.dataset.mode && +c.dataset.mode === mode)) { c.classList.add("selected-item"); } else { c.classList.remove("selected-item"); } }); render(); }); render(); root.addEventListener("click", function (e) { var b = e.target.closest("button.chip"); if (!b) return; if (b.dataset.rev || b.dataset.budget || b.dataset.mode) { setTimeout(renderTable, 0); } }, true); }; /* ---------- Accordion FAQ (§8.11) ---------- */ window.AIX_faq = function (root) { if (!root) return; var items = root.querySelectorAll(".acc-item"); items.forEach(function (it, i) { var btn = it.querySelector(".acc-btn"); btn.addEventListener("click", function () { var open = it.classList.contains("open"); items.forEach(function (x) { x.classList.remove("open"); }); if (!open) it.classList.add("open"); }); if (i === 0) it.classList.add("open"); }); }; /* ---------- Thanh anchor hub (§8.2) ---------- */ window.AIX_anchor = function () { var bar = document.querySelector(".anchor-bar"); if (!bar) return; var links = bar.querySelectorAll("a"); var spy = function () { var pos = window.scrollY + 160, cur = null; links.forEach(function (a) { var sec = document.querySelector(a.getAttribute("href")); if (sec && sec.offsetTop <= pos) cur = a; }); links.forEach(function (a) { a.classList.toggle("active", a === cur); }); }; window.addEventListener("scroll", spy, { passive: true }); spy(); }; /* ---------- Render thẻ nhóm & hub (dữ liệu thuần) ---------- */ function renderGroupCards() { var host = document.getElementById("group-cards"); if (!host || !A.groups) return; host.innerHTML = A.groups.map(function (g) { var cls = g.featured ? "group-card-featured card" : "group-card"; var chip = g.industries.map(function (i) { return '' + esc(i.name) + (i.hasHub ? "" : "") + ""; }).join(""); var probs = g.problems.map(function (p) { return "
  • " + esc(p) + "
  • "; }).join(""); if (g.featured) { return '

    ' + esc(g.name) + '

    ' + g.industries.length + " ngành
    " + '
    ' + chip + "
    " + '
    '; } return '

    ' + esc(g.name) + '

    ' + g.industries.length + " ngành
    " + '
    ' + chip + "
    " + '" + '
    Giải pháp ngành →' + 'Chẩn đoán
    '; }).join(""); } document.addEventListener("DOMContentLoaded", function () { buildHeader(); buildFooter(); renderGroupCards(); var sel = document.querySelector("[data-aix-selector]"); if (sel) window.AIX_selector(sel); var roi = document.querySelector("[data-aix-roi]"); if (roi) window.AIX_roi(roi); var faq = document.querySelector("[data-aix-faq]"); if (faq) window.AIX_faq(faq); window.AIX_anchor(); }); })();